﻿/**
 * Stardust Particle Engine
 * 
 * Homepage
 * 	http://code.google.com/p/stardust-particle-engine/
 * 
 * PDF Manual
 * 	http://stardust-particle-engine.googlecode.com/svn/trunk/manual/Stardust%20Particle%20Engine%20Manual.pdf
 */

package {
	import com.bit101.components.PushButton;
	import flash.display.Sprite;
	import flash.events.Event;
	import idv.cjcat.stardust.common.clocks.ImpulseClock;
	import idv.cjcat.stardust.twoD.renderers.DisplayObjectRenderer;
	
	[SWF(backgroundColor="#FFFFFF", frameRate=60)]
	
	public class Main extends Sprite {
		
		public static const ANT_COUNT:int = 70;
		
		private var emitter:AntEmitter;
		
		public function Main():void {
			
			//Stardust
			//------------------------------------------------------------------------------------------------
				
				//container
				var container:Sprite = new Sprite();
				addChild(container);
				
				//emitter & renderer
				var clock:ImpulseClock = new ImpulseClock(ANT_COUNT);
				clock.impulse();
				emitter = new AntEmitter(clock);
				var renderer:DisplayObjectRenderer = new DisplayObjectRenderer(container);
				renderer.addEmitter(emitter);
				
			//------------------------------------------------------------------------------------------------
			
			
			//UI
			//------------------------------------------------------------------------------------------------
				
				//speed buttons
				var btn1X:PushButton = new PushButton(this, 10, 10, "1X", changeSpeed);
				var btn2X:PushButton = new PushButton(this, 10, 30, "2X", changeSpeed);
				var btn4X:PushButton = new PushButton(this, 10, 50, "4X", changeSpeed);
				addEventListener(Event.ENTER_FRAME, mainLoop);
				
			//------------------------------------------------------------------------------------------------
		}
		
		private function mainLoop(e:Event):void {
			emitter.step();
		}
		
		private function changeSpeed(e:Event):void {
			var btn:PushButton = e.target as PushButton;
			
			//somehow the "switch" statement causes compile-time error :(
			if (btn.label == "1X") emitter.stepTimeInterval = 1;
			else if (btn.label == "2X") emitter.stepTimeInterval = 2;
			else if (btn.label == "4X") emitter.stepTimeInterval = 4;
		}
	}
}

//------------------------------------------------------------------------------------------------

import flash.display.Shape;
import flash.display.Sprite;
import idv.cjcat.stardust.common.clocks.Clock;
import idv.cjcat.stardust.common.emitters.Emitter;
import idv.cjcat.stardust.common.math.UniformRandom;
import idv.cjcat.stardust.common.particles.Particle;
import idv.cjcat.stardust.twoD.actions.Action2D;
import idv.cjcat.stardust.twoD.actions.Move;
import idv.cjcat.stardust.twoD.actions.Oriented;
import idv.cjcat.stardust.twoD.actions.Deflect;
import idv.cjcat.stardust.twoD.deflectors.WrappingBox;
import idv.cjcat.stardust.twoD.emitters.Emitter2D;
import idv.cjcat.stardust.twoD.geom.Vec2D;
import idv.cjcat.stardust.twoD.geom.Vec2DPool;
import idv.cjcat.stardust.twoD.initializers.DisplayObjectClass;
import idv.cjcat.stardust.twoD.initializers.Position;
import idv.cjcat.stardust.twoD.initializers.Rotation;
import idv.cjcat.stardust.twoD.initializers.Velocity;
import idv.cjcat.stardust.twoD.particles.Particle2D;
import idv.cjcat.stardust.twoD.zones.LazySectorZone;
import idv.cjcat.stardust.twoD.zones.RectZone;

//------------------------------------------------------------------------------------------------

//average speed
const SPEED_AVG:Number = 2;

//speed variation
const SPEED_VAR:Number = 1.5;

//max angle of orientation change per loop
const MAX_ANGLE_CHANGE:Number = 20;

//------------------------------------------------------------------------------------------------

class AntEmitter extends Emitter2D {
	
	public function AntEmitter(clock:Clock) {
		super(clock);
		
		//initializers
		addInitializer(new DisplayObjectClass(Ant));
		addInitializer(new Position(new RectZone(0, 0, 465, 465)));
		addInitializer(new Velocity(new LazySectorZone(SPEED_AVG, SPEED_VAR)));
		addInitializer(new Rotation(new UniformRandom(0, 180)));
		
		//deflect action
		var deflect:Deflect = new Deflect();
		deflect.addDeflector(new WrappingBox(0, 0, 465, 465));
		
		//actions
		addAction(deflect);
		addAction(new Move());
		addAction(new Oriented(1, -90));
		addAction(new ChangeOrientation(MAX_ANGLE_CHANGE));
	}
}

//------------------------------------------------------------------------------------------------

class ChangeOrientation extends Action2D {
	
	private var _maxAngleChnage:Number;
	
	public function ChangeOrientation(maxAngleChange:Number) {
		_maxAngleChnage = maxAngleChange;
	}
	
	override public function update(emitter:Emitter, particle:Particle, time:Number):void {
		var p2D:Particle2D = particle as Particle2D;
		var vec:Vec2D = Vec2DPool.get(p2D.vx, p2D.vy);
		vec.rotateThis(2 * (Math.random() - 0.5) * _maxAngleChnage);
		p2D.vx = vec.x;
		p2D.vy = vec.y;
		Vec2DPool.recycle(vec);
	}
}

//------------------------------------------------------------------------------------------------

class Ant extends Sprite {
	private var ant:Sprite;

	public function Ant(){
		drawAnt();
	}
	
	//アリの見た目がしょぼいです・・
	private function drawAnt():void {
		ant = new Sprite();
		ant.scaleX = ant.scaleY = 0.3;
		this.addChild(ant);
			
		var hip:Shape = new Shape();
		hip.graphics.beginFill(0x000000, 1);
		hip.graphics.drawEllipse(-23, -9, 19, 18);
		hip.graphics.endFill();
		ant.addChild(hip);
		
		var head:Shape = new Shape();
		head.graphics.beginFill(0x000000, 1);
		head.graphics.drawEllipse(9, -9, 19, 18);
		head.graphics.endFill();
		ant.addChild(head);

		var body:Shape = new Shape();
		body.graphics.beginFill(0x000000, 1);
		body.graphics.drawEllipse(-14, -10, 28, 20);
		body.graphics.endFill();
		ant.addChild(body);
		
		var reg:Shape = new Shape();
		reg.graphics.lineStyle(2, 0x000000, 1);
		reg.graphics.moveTo(10, 0);
		reg.graphics.lineTo(15, 15);
		reg.graphics.lineTo(30, 20);
		reg.graphics.moveTo(10, 0);
		reg.graphics.lineTo(15, -15);
		reg.graphics.lineTo(30, -20);
		reg.graphics.moveTo(0, 0);
		reg.graphics.lineTo(0, 15);
		reg.graphics.lineTo(-10, 20);
		reg.graphics.moveTo(0, 0);
		reg.graphics.lineTo(0, -15);
		reg.graphics.lineTo(-10, -20);
		reg.graphics.moveTo(-10, 0);
		reg.graphics.lineTo(-15, 15);
		reg.graphics.lineTo(-30, 20);
		reg.graphics.moveTo(-10, 0);
		reg.graphics.lineTo(-15, -15);
		reg.graphics.lineTo(-30, -20);
		ant.addChild(reg);
	}
}